
#include <linux/module.h>
#include <linux/version.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>

#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/gpio.h>

struct pin_desc{
	int irq;
	char *name;
	unsigned int pin;
	unsigned int keyval;
};

struct pin_desc pins_desc[4] = {
	{IRQ_EINT0,  "S2", S3C2410_GPF0,   KEY_L},
	{IRQ_EINT2,  "S3", S3C2410_GPF2,   KEY_S},
	{IRQ_EINT11, "S4", S3C2410_GPG3,   KEY_ENTER},
	{IRQ_EINT19, "S5",  S3C2410_GPG11, KEY_LEFTSHIFT},
};

static struct timer_list button_timer;

static struct input_dev *button_dev;

static struct pin_desc *irq_pd;

static irqreturn_t buttons_irq(int irq, void *dev_id)
{
	irq_pd = (struct pin_desc *)dev_id;
	mod_timer(&button_timer, jiffies+HZ/100);
	return IRQ_HANDLED;
}

static void button_timer_func(unsigned long data)
{
	unsigned int keyval;
	struct pin_desc *pindesc = irq_pd;

	if(!pindesc)
		return;
	keyval = s3c2410_gpio_getpin(pindesc->pin);

	if(keyval)
	{
		input_event(button_dev, EV_KEY, pindesc->keyval, 0);
		input_sync(button_dev);
	}
	else
	{
		input_event(button_dev, EV_KEY, pindesc->keyval, 1);
		input_sync(button_dev);
	}
}

static int buttons_input_init(void)
{
	int i;

	button_dev = input_allocate_device();

	set_bit(EV_KEY, button_dev->evbit);
	set_bit(EV_REP, button_dev->evbit);
	
	set_bit(KEY_L, button_dev->keybit);
	set_bit(KEY_S, button_dev->keybit);
	set_bit(KEY_ENTER, button_dev->keybit);
	set_bit(KEY_LEFTSHIFT, button_dev->keybit);

	input_register_device(button_dev);

	init_timer(&button_timer);
	button_timer.function = button_timer_func;
	add_timer(&button_timer);

	for(i = 0; i < 4; i++)
	{
		request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);
	}
	
	return 0;
}

static void buttons_input_exit(void)
{
	int i;
	for(i = 0; i < 4; i++)
	{
		free_irq(pins_desc[i].irq, &pins_desc[i]);
	}
	del_timer(&button_timer);
	input_unregister_device(button_dev);
	input_free_device(button_dev);
}

module_init(buttons_input_init);
module_exit(buttons_input_exit);

MODULE_LICENSE("GPL");


